home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / sockuser.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  8.2 KB  |  421 lines

  1. #include "global.h"
  2. #ifdef    ANSIPROTO
  3. #include <stdarg.h>
  4. #endif
  5. #include "mbuf.h"
  6. #include "proc.h"
  7. #include "socket.h"
  8. #include "usock.h"
  9. #include "session.h"
  10. #include "nr4.h"
  11.  
  12. static int rrecvchar __ARGS((struct usock *up,int s));
  13.  
  14. /* Higher-level receive routine, intended for connection-oriented sockets.
  15.  * Can be used with datagram sockets, although the sender id is lost.
  16.  */
  17. int
  18. recv(s,buf,len,flags)
  19. int s;        /* Socket index */
  20. char *buf;    /* User buffer */
  21. int len;    /* Max length to receive */
  22. int flags;    /* Unused; will eventually select oob data, etc */
  23. {
  24.     struct mbuf *bp;
  25.     int cnt;
  26.  
  27.     if(len == 0)
  28.         return 0;    /* Otherwise would be interp as "all" */
  29.  
  30.     cnt = recv_mbuf(s,&bp,flags,NULLCHAR,(int *)NULL);
  31.     if(cnt > 0){
  32.         cnt = min(cnt,len);
  33.         pullup(&bp,buf,(int16)cnt);
  34.         free_p(bp);
  35.     }
  36.     return cnt;
  37. }
  38. /* Higher level receive routine, intended for datagram sockets. Can also
  39.  * be used for connection-oriented sockets, although from and fromlen are
  40.  * ignored.
  41.  */
  42. int
  43. recvfrom(s,buf,len,flags,from,fromlen)
  44. int s;        /* Socket index */
  45. char *buf;    /* User buffer */
  46. int len;    /* Maximum length */
  47. int flags;    /* Unused; will eventually select oob data, etc */
  48. char *from;    /* Source address, only for datagrams */
  49. int *fromlen;    /* Length of source address */
  50. {
  51.     struct mbuf *bp;
  52.     register int cnt;
  53.  
  54.     cnt = recv_mbuf(s,&bp,flags,from,fromlen);
  55.     if(cnt > 0){
  56.         cnt = min(cnt,len);
  57.         pullup(&bp,buf,(int16)cnt);
  58.         free_p(bp);
  59.     }
  60.     return cnt;
  61. }
  62. /* High level send routine */
  63. int
  64. send(s,buf,len,flags)
  65. int s;        /* Socket index */
  66. char *buf;    /* User buffer */
  67. int len;    /* Length of buffer */
  68. int flags;    /* Unused; will eventually select oob data, etc */
  69. {
  70.     register struct mbuf *bp;
  71.     char sock[MAXSOCKSIZE];
  72.     int i = MAXSOCKSIZE;
  73.  
  74.     if(getpeername(s,sock,&i) == -1)
  75.         return -1;
  76.     bp = qdata(buf,(int16)len);
  77.     return send_mbuf(s,bp,flags,sock,i);
  78. }
  79. /* High level send routine, intended for datagram sockets. Can be used on
  80.  * connection-oriented sockets, but "to" and "tolen" are ignored.
  81.  */
  82. int
  83. sendto(s,buf,len,flags,to,tolen)
  84. int s;        /* Socket index */
  85. char *buf;    /* User buffer */
  86. int len;    /* Length of buffer */
  87. int flags;    /* Unused; will eventually select oob data, etc */
  88. char *to;    /* Destination, only for datagrams */
  89. int tolen;    /* Length of destination */
  90. {
  91.     register struct mbuf *bp;
  92.  
  93.     bp = qdata(buf,(int16)len);
  94.     return send_mbuf(s,bp,flags,to,tolen);
  95. }
  96. /* Receive a newline-terminated line from a socket, returning # chars read.
  97.  * The end-of-line sequence is recognized and translated into a single '\n'.
  98.  */
  99. int
  100. recvline(s,buf,len)
  101. int s;        /* Socket index */
  102. char *buf;    /* User buffer */
  103. unsigned len;    /* Length of buffer */
  104. {
  105.     int c;
  106.     int cnt = 0;
  107.  
  108.     while(len-- > 1){
  109.         if((c = recvchar(s)) == EOF){
  110.             cnt = -1;
  111.             break;
  112.         }
  113.         if(buf != NULLCHAR)
  114.             *buf++ = c;
  115.         cnt++;
  116.         if(uchar(c) == '\n')
  117.             break;
  118.     }
  119.     if(buf != NULLCHAR)
  120.         *buf = '\0';
  121.     return cnt;
  122. }
  123. #if    defined(ANSIPROTO)
  124. /* Do printf on a user socket */
  125. int
  126. usprintf(int s,char *fmt,...)
  127. {
  128.     va_list args;
  129.     int len;
  130.  
  131.     va_start(args,fmt);
  132.     len = usvprintf(s,fmt,args);
  133.     va_end(args);
  134.     return len;
  135. }
  136. /* Printf on standard output socket */
  137. int
  138. tprintf(char *fmt,...)
  139. {
  140.     va_list args;
  141.     int len;
  142.  
  143.     va_start(args,fmt);
  144.     len = usvprintf(Curproc->output,fmt,args);
  145.     va_end(args);
  146.     return len;
  147. }
  148. /* The guts of printf, uses variable arg version of sprintf */
  149. int
  150. usvprintf(int s,char *fmt, va_list args)
  151. {
  152.     int len,withargs;
  153.     register int i;
  154.     char *buf;
  155.     register char *cp;
  156.  
  157.     if(strchr(fmt,'%') == NULLCHAR){
  158.         /* No args, so we don't need vsprintf() */
  159.         withargs = 0;
  160.         buf = fmt;
  161.         len = strlen(fmt);
  162.     } else {
  163.         /* Use a default value that is hopefully longer than the
  164.          * biggest output string we'll ever print (!)
  165.          */
  166.         withargs = 1;
  167.         buf = mallocw(SOBUF);
  168.         vsprintf(buf,fmt,args);
  169.         len = strlen(buf);
  170.     }
  171.     cp = buf;
  172.     i = len;
  173.     while(i-- > 0)
  174.         usputc(s,*cp++);
  175.     if(withargs)
  176.         free(buf);
  177.     return len;
  178. }
  179. #else
  180. /*VARARGS*/
  181. /* Printf to standard output socket */
  182. int
  183. tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  184. char *fmt;        /* Message format */
  185. int arg1,arg2,arg3;    /* Arguments */
  186. int arg4,arg5,arg6;
  187. int arg7,arg8,arg9;
  188. int arg10,arg11,arg12;
  189. {
  190.     return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6
  191.         arg7,arg8,arg9,arg10,arg11,arg12);
  192. }
  193. /* Printf to socket. Doesn't use ANSI vsprintf */
  194. int
  195. usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  196. int s;            /* Socket index */
  197. char *fmt;        /* Message format */
  198. int arg1,arg2,arg3;    /* Arguments */
  199. int arg4,arg5,arg6;
  200. int arg7,arg8,arg9;
  201. int arg10,arg11,arg12;
  202. {
  203.     int len,withargs;
  204.     register int i;
  205.     char *buf;
  206.     register char *cp;
  207.  
  208.     if(strchr(fmt,'%') == NULLCHAR){
  209.         /* No args, so we don't need vsprintf() */
  210.         withargs = 0;
  211.         buf = fmt;
  212.         len = strlen(fmt);
  213.     } else {
  214.         /* Use a default value that is hopefully longer than the
  215.          * biggest output string we'll ever print (!)
  216.          */
  217.         withargs = 1;
  218.         buf = mallocw(SOBUF);
  219.         sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7
  220.          arg8,arg9,arg10,arg11,arg12);
  221.         len = strlen(buf);
  222.     }
  223.     cp = buf;
  224.     i = len;
  225.     while(i-- > 0)
  226.         usputc(s,*cp++);
  227.     if(withargs)
  228.         free(buf);
  229.     return len;
  230. }
  231. #endif
  232. /* Buffered putchar to a socket */
  233. int
  234. usputc(s,c)
  235. int s;
  236. char c;
  237. {
  238.     struct usock *up;
  239.     register struct mbuf *bp;
  240.     char *cp;
  241.  
  242.     if((up = itop(s)) == NULLUSOCK){
  243.         errno = EBADF;
  244.         return -1;
  245.     }
  246.     if(up->obuf == NULLBUF){
  247.         /* Allocate a buffer of appropriate size */
  248.         switch(up->type){
  249.         case TYPE_NETROML4:
  250.             up->obuf = alloc_mbuf(NR4MAXINFO);
  251.             break;
  252.         default:
  253.             up->obuf = alloc_mbuf(BUFSIZ);
  254.             break;
  255.         }
  256.     }
  257.     bp = up->obuf;
  258.     if(c == '\n' && up->eol[0] != '\0'){
  259.         /* Translate into appropriate end-of-line sequence */
  260.         for(cp = up->eol;*cp != '\0';cp++)
  261.             bp->data[bp->cnt++] = *cp;
  262.     } else {
  263.         bp->data[bp->cnt++] = c;
  264.     }
  265.     if((c == up->flush && up->flush != -1) || bp->cnt >= bp->size-2)
  266.         usflush(s);
  267.  
  268.     return (int)uchar(c);
  269. }
  270. /* Put a character to standard output socket */
  271. int
  272. tputc(c)
  273. char c;
  274. {
  275.     return usputc(Curproc->output,c);
  276. }
  277. int
  278. usputs(s,x)
  279. int s;
  280. register char *x;
  281. {
  282.     while(*x != '\0')
  283.         if(usputc(s,*x++) == EOF)
  284.             return EOF;
  285.     return 0;
  286. }
  287.  
  288. /* Put a string to standard output socket */
  289. int
  290. tputs(s)
  291. char *s;
  292. {
  293.     return usputs(Curproc->output,s);
  294. }
  295.  
  296. /* Read a raw character from a socket with stream buffering. */
  297. static int
  298. rrecvchar(up,s)
  299. register struct usock *up;
  300. int s;            /* Socket index */
  301. {
  302.     char c;
  303.  
  304.     /* Replenish if necessary */
  305.     if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0)
  306.         return EOF;
  307.  
  308.     if(pullup(&up->ibuf,&c,1) == 1)
  309.         return (int)uchar(c);
  310.     else
  311.         return EOF;
  312. }
  313. /* This function recognizes the end-of-line sequence for the stream
  314.  * and translates it into a single '\n'.
  315.  */
  316. int
  317. recvchar(s)
  318. int s;            /* Socket index */
  319. {
  320.     int c;
  321.     register struct usock *up;
  322.  
  323.     if((up = itop(s)) == NULLUSOCK)
  324.         return EOF;
  325.  
  326.     c = rrecvchar(up,s);
  327.  
  328.     if(c != up->eol[0] || up->eol[0] == '\0')
  329.         return (int)c;
  330.  
  331.     /* This is the first char of a eol sequence. If the eol sequence is
  332.      * more than one char long, eat the next character in the input stream.
  333.      */
  334.     if(up->eol[1] != '\0'){
  335.         (void)rrecvchar(up,s);
  336.     }
  337.     return '\n';
  338. }
  339. /* Flush output on a socket stream */
  340. void
  341. usflush(s)
  342. int s;
  343. {
  344.     register struct usock *up;
  345.     struct mbuf *bp;
  346.  
  347.     if((up = itop(s)) == NULLUSOCK)
  348.         return;
  349.  
  350.     if(up->obuf != NULLBUF){
  351.         bp = up->obuf;
  352.         up->obuf = NULLBUF;
  353.         send_mbuf(s,bp,0,NULLCHAR,0);
  354.     }
  355. }
  356. /* Flush output socket */
  357. void
  358. tflush()
  359. {
  360.     usflush(Current->output);
  361. }
  362.  
  363. /* Print prompt and read one character */
  364. int
  365. keywait(prompt,flush)
  366. char *prompt;    /* Optional prompt */
  367. int flush;    /* Flush queued input? */
  368. {
  369.     int c;
  370.  
  371.     if(flush && socklen(Curproc->input,1) != 0)
  372.         recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
  373.     if(prompt != NULLCHAR)
  374.         tprintf(prompt);
  375.     else
  376.         tprintf("Hit enter to continue");
  377.     tflush();
  378.     if((c = recvchar(Curproc->input)) == EOF)
  379.         return -1;
  380.     tprintf("\r%75s\r"," ");
  381.     tflush();
  382.     return (int)c;
  383. }
  384.  
  385. /* Set the end-of-line sequence on a socket */
  386. int
  387. seteol(s,seq)
  388. int s;
  389. char *seq;
  390. {
  391.     register struct usock *up;
  392.  
  393.     if((up = itop(s)) == NULLUSOCK)
  394.         return -1;
  395.  
  396.     if(seq != NULLCHAR)
  397.         strncpy(up->eol,seq,sizeof(up->eol));
  398.     else
  399.         *up->eol = '\0';
  400.     return 0;
  401. }
  402. /* Specify the character to trigger automatic output buffer
  403.  * flushing, or -1 to disable it
  404.  */
  405. int
  406. setflush(s,c)
  407. int s;
  408. int c;
  409. {
  410.     register struct usock *up;
  411.     int old;
  412.  
  413.     if((up = itop(s)) == NULLUSOCK)
  414.         return -1;
  415.  
  416.     old = up->flush;
  417.     up->flush = c;
  418.     return old;
  419. }
  420.  
  421.